import { ref } from 'vue';

export function useSingleDocCodeGeneration() {
  const generatedCode = ref('');
    
  const generateTypeDefinition = (tableConfig) => {
    const { tableName, data } = tableConfig;
    
    const fieldsDefinition = data.map((field, index) => {
      const [table, fieldName] = field.referenceTableField?.split('.') || [];
      const isLastField = index === data.length - 1;
      const comma = isLastField ? '' : ',';
      return `       ${field.field.padEnd(20)} LIKE ${table}.${fieldName || field.field}${comma}`.padEnd(65) + `#${field.description}`;
    }).join('\n');

    return `TYPE   ${tableName}      RECORD     \n${fieldsDefinition}\n      END RECORD`;
  };

  //表格中的主键字段
  const primaryKeyFields = (tableConfig) => {
    return tableConfig.data
      .filter(field => field.keyword === 'Y')
      .map(field => field.field)[0];
  };

  const programName = (formData) => {
    return `${formData.programId.slice(3)}`;
  };

  const generateSingleDocCode = (formData, tableConfig) => {
    // Get primary key fields for WHERE clause
    const pkFields = tableConfig.data
      .filter(field => field.keyword === 'Y')
      .map(field => field.field);

    // Build WHERE clause with all primary keys
    const whereClause = pkFields.map(field => `${field}=?`).join(' AND ');

    // Get first primary key field for error messages
    const primaryKeyField = primaryKeyFields(tableConfig);

    // Uinsg key fields
    const usingKeyFields = tableConfig.data.filter(field => field.keyword === 'Y').map(field => field.field).join(',');

    // 程序中命名
    const programNameId = programName(formData);

    //字段
    const fields = tableConfig.data.map(field => field.field).join(',');

    //界面数组
    const formName = tableConfig.data.map(field => `${formData.formName}[1].${field.field}`).join(',');

    //数据复制
    const arrayMoveTo = tableConfig.data.map(field => `     LET  ${tableConfig.arrayName}[g_ac].${field.field} = g_detail.${field.field}`).join('\n');

    //数据退回
    const arrayMoveBack = tableConfig.data.map(field => `    LET g_detail.${field.field} = ${tableConfig.arrayName}[g_ac].${field.field}`).join('\n');  

    //字段必填
    const fieldRequired = tableConfig.data.filter(field => field.keyword === 'Y').map(field => `    CALL cl_set_comp_entry("${field.field}",TRUE)`).join('\n');
   
    //字段不可输入
    const fieldNoInput = tableConfig.data.filter(field => field.keyword === 'Y').map(field => `    CALL cl_set_comp_entry("${field.field}",FALSE)`).join('\n');
   

    let code = `

# 程序名称: ${formData.programId}
# 作   者: ${formData.author}
# 创建时间: ${new Date().toLocaleString()}


DATABASE ds
GLOBALS "../../../tiptop/config/top.global"

${generateTypeDefinition(tableConfig)}
DEFINE ${tableConfig.arrayName}   DYNAMIC ARRAY OF ${tableConfig.tableName}      #单身全局
DEFINE ${tableConfig.arrayName}_t   ${tableConfig.tableName}                     #单身旧值
DEFINE g_detail               RECORD LIKE ${tableConfig.insertTable}.*           #单身Record
DEFINE g_ac                   LIKE type_file.num10                               #光标所在NO.
DEFINE g_rec_b                LIKE type_file.num10                               #单身总笔数
DEFINE g_wc                   STRING                                             #定义CONSTRUCT接受变量

DEFINE g_sql               STRING                                          #定义sql
DEFINE g_forupd_sql        STRING                                          #SELECT ... FOR UPDATE  SQL
DEFINE g_before_input_done STRING                                          #判斷是否已執行 Before Input指令
DEFINE g_cnt               LIKE type_file.num10                            #定义gen_file笔数
DEFINE g_curs_index        LIKE type_file.num10                            #获取Fetch当前笔index
DEFINE g_row_count         LIKE type_file.num10                            #获取Fetch总笔数
DEFINE g_jump              LIKE type_file.num10                            #跳转Fetch指定index
DEFINE g_no_ask            LIKE type_file.num10                            #是否开启指定笔視窗
DEFINE g_msg               LIKE type_file.chr1000                          #错误信息
DEFINE g_statebar          STRING                                          #笔数变量

################################################################################
# Descriptions...: 主函数入口
# Memo...........:
# Usage..........: CALL ${formData.programId}()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
MAIN
DEFINE p_row,p_col         LIKE type_file.num5

       OPTIONS
       #FIELD ORDER FORM,                                             
       INPUT NO WRAP                                                 
       DEFER INTERRUPT                                                

       IF (NOT cl_user()) THEN                                       
          EXIT PROGRAM                                                
       END IF

       WHENEVER ERROR CALL cl_err_msg_log                             
       IF (NOT cl_setup("${formData.module}")) THEN                                 
          EXIT PROGRAM                                                
       END IF

       CALL cl_used(g_prog,g_time,1) RETURNING g_time                 

       LET g_forupd_sql = " SELECT * FROM ${tableConfig.insertTable} WHERE ${whereClause} FOR UPDATE  "
       LET g_forupd_sql = cl_forupd_sql(g_forupd_sql)
       DECLARE ${programNameId}_bcl CURSOR FROM g_forupd_sql                       #gen_file CURSOR定义(锁表sql)

       LET g_statebar = "Total: %1 / %2"                              

       LET p_row = 2 
       LET p_col = 2

       OPEN WINDOW ${programNameId}_w AT p_row,p_col WITH FORM "${formData.programPath}"
            ATTRIBUTE (STYLE = g_win_style CLIPPED)                 

       CALL cl_ui_init()                                              

       LET g_action_choice = ""                                       
       CALL ${programNameId}_menu()                                               

       CLOSE WINDOW ${programNameId}_w                                            

       CALL cl_used(g_prog,g_time,2) RETURNING g_time                 

END MAIN

################################################################################
# Descriptions...: 主函数入口
# Memo...........:
# Usage..........: CALL ${programNameId}_menu()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_menu()
DEFINE l_cmd               STRING

       WHILE TRUE
             CALL ${programNameId}_bp("G")
             CASE g_action_choice
                  WHEN "query"
                       IF cl_chk_act_auth() THEN                      
                          CALL ${programNameId}_q()                   
                       END IF

                  WHEN "detail"
                       IF cl_chk_act_auth() THEN                      
                          CALL ${programNameId}_b()                   
                       ELSE
                          LET g_action_choice = NULL
                       END IF

                  WHEN "output"
                       #IF cl_chk_act_auth() THEN                     
                       #   CALL ${programNameId}_out()               
                       #END IF

                  WHEN "help"
                       CALL cl_show_help()                            

                  WHEN "exit"
                       EXIT WHILE                                    

                  WHEN "controlg"
                       CALL cl_cmdask()                              

                  WHEN "locale"
                       CALL cl_dynamic_locale()                      
                       CALL cl_show_fld_cont()                       

                  WHEN "about"
                       CALL cl_about()                                

                  WHEN "related_document"
                       IF cl_chk_act_auth() THEN
                             CALL cl_doc()                            
                       END IF

                  WHEN "exporttoexcel"
                       IF cl_chk_act_auth() THEN
                          CALL cl_export_to_excel(ui.Interface.getRootNode(),base.TypeInfo.create(${tableConfig.arrayName}),'','')
                       END IF

             END CASE
       END WHILE

END FUNCTION

################################################################################
# Descriptions...: 查询条件录入
# Memo...........:
# Usage..........: CALL ${programNameId}_cs()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_cs()

       CLEAR FORM
       CALL ${tableConfig.arrayName}.clear()                                             
       CONSTRUCT g_wc ON ${fields} 
            FROM ${formName}                                    

           BEFORE CONSTRUCT                                          
              CALL cl_qbe_init()                                     

           ON ACTION controlp                                         

           ON IDLE g_idle_seconds
              CALL cl_on_idle()                                      
              CONTINUE CONSTRUCT

           ON ACTION controlg
              CALL cl_cmdask()                                       

           ON ACTION about
              CALL cl_about()                                        

           ON ACTION help
              CALL cl_show_help()                                    

           ON ACTION qbe_select
              CALL cl_qbe_select()                                   

           ON ACTION qbe_save
              CALL cl_qbe_save()                                     

       END CONSTRUCT

      #LET g_wc = g_wc CLIPPED,cl_get_extra_cond('genuser', 'gengrup')     

       IF INT_FLAG THEN
          LET g_wc = NULL
          LET INT_FLAG = 0
          RETURN
       END IF

       CALL ${programNameId}_b_fill(g_wc)

END FUNCTION

################################################################################
# Descriptions...: 查询执行
# Memo...........:
# Usage..........: CALL ${programNameId}_cs()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_q()
      CALL ${programNameId}_cs()       
END FUNCTION

################################################################################
# Descriptions...: 界面显示
# Memo...........:
# Usage..........: CALL ${programNameId}_bp(p_ud)
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_bp(p_ud)
DEFINE p_ud                LIKE type_file.chr1

       IF p_ud <> "G" OR g_action_choice = "detail" THEN
          RETURN
       END IF

       LET g_action_choice = " "

       CALL cl_set_act_visible("accept,cancel", FALSE)
       DISPLAY ARRAY ${tableConfig.arrayName} TO ${formData.formName}.* ATTRIBUTE(COUNT=g_rec_b,UNBUFFERED)

               BEFORE DISPLAY
                  CALL cl_navigator_setting(g_curs_index, g_row_count) 

               BEFORE ROW
                  LET g_ac = ARR_CURR()                             
                  CALL cl_show_fld_cont()                             
                  MESSAGE SFMT(g_statebar,g_ac,g_rec_b)

               ON ACTION query
                  LET g_action_choice="query"
                  EXIT DISPLAY

               ON ACTION detail
                  LET g_action_choice="detail"
                  LET g_ac = 1
                  EXIT DISPLAY

               ON ACTION help
                  LET g_action_choice="help"
                  EXIT DISPLAY

               ON ACTION locale
                  LET g_action_choice="locale"

               #ON ACTION output
                  #LET g_action_choice="output"
                  #EXIT DISPLAY

               ON ACTION accept
                  LET g_ac = ARR_CURR()
                  LET g_action_choice="detail"
                  EXIT DISPLAY

               ON ACTION exit
                  LET g_action_choice="exit"
                  EXIT DISPLAY

               ON ACTION cancel
                  LET INT_FLAG=FALSE
                  LET g_action_choice="exit"
                  EXIT DISPLAY

               ON ACTION close
                  LET g_action_choice="exit"
                  EXIT DISPLAY

               ON ACTION controlg
                  LET g_action_choice="controlg"
                  EXIT DISPLAY

               ON IDLE g_idle_seconds
                  CALL cl_on_idle()
                  CONTINUE DISPLAY

               ON ACTION about
                  LET g_action_choice="about"

               ON ACTION related_document
                  LET g_action_choice="related_document"
                  EXIT DISPLAY

               ON ACTION exporttoexcel
                  LET g_action_choice="exporttoexcel"
                  EXIT DISPLAY

               ON ACTION controls
                  CALL cl_set_head_visible("","AUTO")                 

               AFTER DISPLAY
                     CONTINUE DISPLAY

       END DISPLAY
       CALL cl_set_act_visible("accept,cancel", TRUE)

END FUNCTION

################################################################################
# Descriptions...: 单身编辑
# Memo...........:
# Usage..........: CALL ${programNameId}_b()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_b()
DEFINE p_cmd               LIKE type_file.chr1
DEFINE l_lock_sw           LIKE type_file.chr1
DEFINE l_allow_insert      LIKE type_file.chr1
DEFINE l_allow_delete      LIKE type_file.chr1

       LET g_action_choice = ""

       IF s_shut(0) THEN RETURN END IF                                #判断目前系统是否可用

       CALL cl_opmsg('b')                                             #界面左下角显示操作形态
       LET g_action_choice = ""                                       #初始化Action执行标示

       LET l_allow_insert = cl_detail_input_auth('insert')            #单身是否有insert/delete权限
       LET l_allow_delete = cl_detail_input_auth('delete')            #单身是否有insert/delete权限

       INPUT ARRAY ${tableConfig.arrayName} WITHOUT DEFAULTS FROM ${formData.formName}.*
              ATTRIBUTE (COUNT=g_rec_b,MAXCOUNT=g_max_rec,UNBUFFERED,
                        INSERT ROW = l_allow_insert,DELETE ROW=l_allow_delete,APPEND ROW=l_allow_insert)

       BEFORE INPUT
          IF g_rec_b != 0 THEN  
             CALL fgl_set_arr_curr(g_ac)
          END IF
          
       BEFORE ROW
          LET p_cmd=''
          LET g_ac = ARR_CURR()
          LET l_lock_sw = 'N'

          IF g_rec_b >= g_ac THEN
             BEGIN WORK
             LET p_cmd='u'
             LET ${tableConfig.arrayName}_t.* = ${tableConfig.arrayName}[g_ac].*

             OPEN ${programNameId}_bcl USING ${tableConfig.data.filter(field => field.keyword === 'Y').map(field => `${tableConfig.arrayName}[g_ac].${field.field}`).join(',')}
             IF STATUS THEN
                CALL cl_err("OPEN ${programNameId}_bcl:", STATUS, 1)
                LET l_lock_sw = 'Y'
             ELSE
                FETCH ${programNameId}_bcl INTO ${tableConfig.arrayName}[g_ac].*
                IF SQLCA.sqlcode THEN
                   CALL cl_err(" FETCH ${programNameId}_bcl:", SQLCA.sqlcode, 1)
                   LET l_lock_sw = 'Y'
                END IF
                CALL ${programNameId}_b_move_to()
             END IF

             CALL cl_show_fld_cont()                                  
          END IF

          MESSAGE SFMT(g_statebar,g_ac,g_cnt)      


       BEFORE INSERT

          LET p_cmd='a'
          INITIALIZE ${tableConfig.arrayName}[g_ac].* TO NULL
          LET ${tableConfig.arrayName}_t.* = ${tableConfig.arrayName}[g_ac].*
          CALL cl_show_fld_cont()
          NEXT FIELD ${primaryKeyField}

       AFTER INSERT
          IF INT_FLAG THEN
             CALL cl_err('',9001,0)                                   
             LET INT_FLAG = 0
             CLOSE ${programNameId}_bcl
             CANCEL INSERT
          END IF

          BEGIN WORK

          CALL ${programNameId}_b_move_back()
          INSERT INTO ${tableConfig.insertTable} VALUES(${tableConfig.arrayName}[g_ac].*)
          IF SQLCA.sqlcode THEN                                       
             CALL cl_err3("ins","${tableConfig.tableName}", ${tableConfig.arrayName}[g_ac].${primaryKeyField},"",SQLCA.sqlcode,"","",0)
             ROLLBACK WORK
             CANCEL INSERT 
          ELSE
             MESSAGE 'INSERT O.K'
             COMMIT WORK
             LET g_rec_b = g_rec_b + 1
             MESSAGE SFMT(g_statebar,g_ac,g_rec_b)
          END IF

       BEFORE DELETE
          IF ${tableConfig.data
              .filter(field => field.keyword === 'Y')
              .map(field => `${tableConfig.arrayName}_t.${field.field}`)
              .join(' AND ')} IS NOT NULL THEN
             IF NOT cl_delb(0,0) THEN
                CANCEL DELETE
             END IF
             IF l_lock_sw = 'Y' THEN
                CALL cl_err("", -263, 1)
                CANCEL DELETE
             END IF

             DELETE FROM ${tableConfig.insertTable}
              WHERE ${tableConfig.data
                  .filter(field => field.keyword === 'Y')
                  .map(field => `${field.field} = ${tableConfig.arrayName}_t.${field.field}`)
                  .join(' AND ')}

             IF SQLCA.sqlcode THEN
                CALL cl_err3("del","${tableConfig.insertTable}", ${tableConfig.arrayName}_t.${primaryKeyField},"",SQLCA.sqlcode,"","",1) 
                ROLLBACK WORK
                CANCEL DELETE
             END IF
             LET g_rec_b = g_rec_b - 1
             
             MESSAGE SFMT(g_statebar,g_ac,g_rec_b)
          END IF
          COMMIT WORK

       ON ROW CHANGE
          IF INT_FLAG THEN
             CALL cl_err('',9001,0)
             LET INT_FLAG = 0
             LET ${tableConfig.arrayName}[g_ac].* = ${tableConfig.arrayName}_t.*
             CLOSE ${programNameId}_bcl
             ROLLBACK WORK
             EXIT INPUT
          END IF
          IF l_lock_sw='Y' THEN
             CALL cl_err(${tableConfig.arrayName}[g_ac].${primaryKeyField},-263,0)
             LET ${tableConfig.arrayName}[g_ac].* = ${tableConfig.arrayName}_t.*
          ELSE
             CALL ${programNameId}_b_move_back()
               UPDATE ${tableConfig.insertTable} SET * = g_detail.*
                WHERE ${tableConfig.data
                  .filter(field => field.keyword === 'Y')
                  .map(field => `${field.field} = ${tableConfig.arrayName}_t.${field.field}`)
                  .join(' AND ')}

             IF SQLCA.sqlcode THEN
                CALL cl_err3("upd","${tableConfig.tableName}",${tableConfig.arrayName}_t.${primaryKeyField},"",SQLCA.sqlcode,"","",0)
                ROLLBACK WORK
                LET ${tableConfig.arrayName}[g_ac].* = ${tableConfig.arrayName}_t.*
             ELSE
                MESSAGE 'UPDATE O.K'
                COMMIT WORK
             END IF
          END IF

       AFTER ROW
          LET g_ac = ARR_CURR()
          IF INT_FLAG THEN
             LET INT_FLAG = 0
             CALL cl_err('',9001,0)
             IF p_cmd='u' THEN
                LET ${tableConfig.arrayName}[g_ac].* = ${tableConfig.arrayName}_t.*
             END IF
             CLOSE ${programNameId}_bcl
             ROLLBACK WORK
             EXIT INPUT
          END IF
          CLOSE ${programNameId}_bcl
          COMMIT WORK

       ON ACTION controlp                                            

       ON ACTION controlr
          CALL cl_show_req_fields()                                   

       ON ACTION controlg
          CALL cl_cmdask()                                            

       ON ACTION controlf
          CALL cl_set_focus_form(ui.Interface.getRootNode())
               RETURNING g_fld_name,g_frm_name                        
          CALL cl_fldhelp(g_frm_name,g_fld_name,g_lang)               

       ON IDLE g_idle_seconds
          CALL cl_on_idle()                                           
          CONTINUE INPUT

       ON ACTION about
          CALL cl_about()                                            

       ON ACTION help
          CALL cl_show_help()                                         

       END INPUT

       CLOSE ${programNameId}_bcl
       COMMIT WORK      

END FUNCTION

################################################################################
# Descriptions...: 单身数据获取
# Memo...........:
# Usage..........: CALL ${programNameId}_b_fill(p_wc)
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_b_fill(p_wc)
DEFINE p_wc                STRING

       LET g_sql = " SELECT ${fields} FROM ${tableConfig.insertTable} WHERE ",p_wc CLIPPED
       PREPARE ${programNameId}_b_fill_prepare FROM g_sql
       DECLARE ${programNameId}_b_fill_curs CURSOR FOR ${programNameId}_b_fill_prepare   

       CALL ${tableConfig.arrayName}.clear()
       LET g_cnt = 1
       MESSAGE "Searching!"

       FOREACH ${programNameId}_b_fill_curs INTO ${tableConfig.arrayName}[g_cnt].*      
          IF STATUS THEN
             CALL cl_err('foreach:',STATUS,1)
             EXIT FOREACH
          END IF

          LET g_cnt = g_cnt + 1
          IF g_cnt > g_max_rec THEN
             CALL cl_err('', 9035,0)
             EXIT FOREACH
          END IF
       END FOREACH

       CALL ${tableConfig.arrayName}.deleteElement(g_cnt)
       LET g_rec_b = g_cnt - 1

       LET g_cnt = 0

END FUNCTION

################################################################################
# Descriptions...: 数据复制
# Memo...........:
# Usage..........: CALL ${programNameId}_b_move_to()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_b_move_to()

${arrayMoveTo}

END FUNCTION

################################################################################
# Descriptions...: 数据退回
# Memo...........:
# Usage..........: CALL ${programNameId}_b_move_back()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
FUNCTION ${programNameId}_b_move_back()

${arrayMoveBack}

END FUNCTION

################################################################################
# Descriptions...: 字段必填
# Memo...........:
# Usage..........: CALL ${programNameId}_b_set_entry(p_cmd)
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################

PRIVATE FUNCTION ${programNameId}_set_entry(p_cmd)
DEFINE   p_cmd               LIKE type_file.chr1

       IF p_cmd = 'a'  AND (NOT g_before_input_done) THEN
           ${fieldRequired}
       END IF

END FUNCTION

################################################################################
# Descriptions...: 字段不可输入
# Memo...........:
# Usage..........: CALL ${programNameId}_set_no_entry(p_cmd)
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
PRIVATE FUNCTION ${programNameId}_set_no_entry(p_cmd)
DEFINE   p_cmd               LIKE type_file.chr1

       IF p_cmd = 'u' AND g_chkey = 'N' THEN
           ${fieldNoInput}
       END IF

END FUNCTION

################################################################################
# Descriptions...: 数据导出
# Memo...........:
# Usage..........: CALL ${programNameId}_out()
# Input parameter:  
# Return code....: 
# Date & Author..: ${new Date().toLocaleString()} By ${formData.author}
# Modify.........:
################################################################################
PRIVATE FUNCTION ${programNameId}_out()
DEFINE l_cmd               LIKE type_file.chr1000
DEFINE l_wc                LIKE type_file.chr1000
DEFINE l_prtway            LIKE type_file.chr1

       CALL cl_wait()

       LET l_wc = ${tableConfig.data
           .filter(field => field.keyword === 'Y')
           .map(field => `'${field.field} = "',${tableConfig.arrayName}[g_ac].${field.field},'"'`)
           .join(',\n                  \' and \'')}

       SELECT zz22 INTO l_prtway FROM zz_file WHERE zz01 = '${formData.programId}'

       LET l_cmd = "${formData.programId}",
              " '",g_today,"' '' '",g_lang,"' 'Y' '",l_prtway,"' '1' '",l_wc CLIPPED,"'"

       CALL cl_cmdrun_wait(l_cmd)

       ERROR ' '

END FUNCTION

`;

    generatedCode.value = code;
    return code;
  };

  return {
    generateSingleDocCode,
    generatedCode
  };
}